//****************************************************
// Porman Project 2
// Filename: CLogger.cpp
// Date: 2011/05/07
// Author: KengYu Lin
// Modify:
//****************************************************
#include "CLogger.h"

namespace Porman
{

namespace GL
{

//-----------------------------
// class CConsoleLogReceiver:
//-----------------------------
bool CConsoleLogReceiver::onLog( const std::string& sLevel, const std::string& sSender, const std::string& sMsg, int iLine )
{
    //-----------------------------------------------------------------------
    // Log format:
    // ThreadID [level] [Sender]: sender_name [Msg]: msg_info [Ln]: line
    //-----------------------------------------------------------------------
#if defined(_WINDOWS) || defined (_WIN32)
    char _g_cLogInfo[2048] = "";
    ::strcat( _g_cLogInfo, "[" ); ::strcat( _g_cLogInfo, sLevel.c_str() ); ::strcat( _g_cLogInfo, "] " ); 
    ::strcat( _g_cLogInfo, "[Sender]:" ); ::strcat( _g_cLogInfo, sSender.c_str() ); 
    ::strcat( _g_cLogInfo, " [Msg]:" ); ::strcat( _g_cLogInfo, sMsg.c_str() ); 

    char cLine[6] = ""; sprintf( cLine, "%d", iLine );
    ::strcat( _g_cLogInfo, " [Ln]:" ); ::strcat( _g_cLogInfo, cLine ); 
    ::strcat( _g_cLogInfo, "\n" );
    OutputDebugString( _g_cLogInfo );
    return true;
#elif
    std::cout << "[" << sLevel << "] " << "[Sender]:" << sSender << " [Msg]:" << sMsg << " [Ln]:" << iLine << std::endl;
    return true;    
#endif
}

//-----------------------------
// class CLogger:
//-----------------------------
static CLogger Logger;

CLogger::CLogger( void ) :
m_enumCurLogLevel(LOG_DEBUG4),
m_ConsoleReveiver()
{
    m_pMutex = new CDefaultMutex();
    registerLogReceiver( &m_ConsoleReveiver, "Console" );
}

CLogger::~CLogger( void )
{
    m_mapLogReceiver.clear();
    SAFEDELETE( m_pMutex );
}

void CLogger::log( LogLevel level, const std::string& sSender, const std::string& sMsg, int iLine )
{
    CMutexObject mutexObj( m_pMutex );
    if( level > m_enumCurLogLevel )
        return;
    else
    {
        static const char* const buffer[] = { "ERROR", "WARNING", "INFO", "DEBUG", "DEBUG1", "DEBUG2", "DEBUG3", "DEBUG4" };

        std::map<std::string, ILogReceiver*>::iterator ite = m_mapLogReceiver.begin();
        std::map<std::string, ILogReceiver*>::iterator iteEnd = m_mapLogReceiver.end();
        for( ite; ite!=iteEnd; ++ite )
        {
            if( ite->second->isEnable() )
                ite->second->onLog( buffer[level], sSender, sMsg, iLine );
        }
    }
}

void CLogger::setLogLevel( LogLevel level )
{
    CMutexObject mutexObj( m_pMutex );
    m_enumCurLogLevel = level;
}

LogLevel CLogger::getLogLevel( void )
{
    CMutexObject mutexObj( m_pMutex );
    return m_enumCurLogLevel;
}

void CLogger::registerLogReceiver( ILogReceiver* pReceiver, const std::string& sName )
{
    CMutexObject mutexObj( m_pMutex );
    m_mapLogReceiver.insert( std::map<std::string, ILogReceiver*>::value_type( sName, pReceiver ) );
}

bool CLogger::removeLogReceiver( const std::string& sName )
{
    CMutexObject mutexObj( m_pMutex );
    std::map<std::string, ILogReceiver*>::iterator ite = m_mapLogReceiver.find( sName );
    if( ite != m_mapLogReceiver.end() )
    {     
        m_mapLogReceiver.erase( ite );
        return true;
    }
    else
        return false;
}

bool CLogger::isLogReceiverRegistered( const std::string& sName )
{
    CMutexObject mutexObj( m_pMutex );
    std::map<std::string, ILogReceiver*>::iterator ite = m_mapLogReceiver.find( sName );
    if( ite != m_mapLogReceiver.end() ) 
        return true;
    else
        return false;
}

ILogReceiver* CLogger::getLogReceiver( const std::string& sName )
{
    CMutexObject mutexObj( m_pMutex );
    std::map<std::string, ILogReceiver*>::iterator ite = m_mapLogReceiver.find( sName );
    if( ite != m_mapLogReceiver.end() ) 
        return ite->second;
    else
        return NULL;
}

}//End namespace GL

}//End nsmespace Porman